/**  
* @Title: StockServiceImpl.java 
* @Description:
* @Copyright: Copyright (c) 2018
* @Company:http://www.sinocon.cn
* @author: Su.Yuanlin  
* @date 2019年3月12日  
* @QQ 314078331  
* @Like 流水落花春去也，天上人间
*/
package com.mtons.mblog.modules.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import com.mtons.mblog.base.utils.BeanMapUtils;
import com.mtons.mblog.modules.data.StockVo;
import com.mtons.mblog.modules.entity.Stock;
import com.mtons.mblog.modules.entity.StockAttr;
import com.mtons.mblog.modules.entity.StockHistory;
import com.mtons.mblog.modules.repository.StockAttrRepository;
import com.mtons.mblog.modules.repository.StockHistroyRepository;
import com.mtons.mblog.modules.repository.StockRepository;
import com.mtons.mblog.modules.service.StockService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

/**
 * @Title: StockServiceImpl
 * @Description:
 * @author:Su.Yuanlin
 * @date 2019年3月12日
 */
@Service
public class StockServiceImpl implements StockService {

	@Autowired
	private StockRepository stockRepository;
	@Autowired
	private StockAttrRepository stockAttrRepository;
	@Autowired
	private StockHistroyRepository stockHistroyRepository;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@PersistenceContext
	private EntityManager entityManager;

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: paging</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param pageable
	 * 
	 * @param channelId
	 * 
	 * @param excludeChannelIds
	 * 
	 * @param ord
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.StockService#paging(org.springframework.
	 * data.domain.Pageable, int, java.util.Set, java.lang.String)
	 * 
	 */
	@Override
	public Page<StockVo> paging(Pageable pageable, int channelId, Set<Integer> excludeChannelIds, String ord) {
		Pageable p = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(),
				new Sort(Sort.Direction.ASC, "popularity"));

		Page<Stock> page = this.stockRepository.findAll(p);
		List<StockVo> rets = new ArrayList<>();

		page.getContent().forEach(po -> {
			rets.add(BeanMapUtils.copy(po));
		});

		return new PageImpl<>(rets, pageable, page.getTotalElements());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: findHotStock</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param maxResults
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.StockService#findHotStock(java.lang.
	 * Integer)
	 * 
	 */
	@Override
	public List<StockVo> findHotStock(Integer maxResults) {
		Pageable pageable = PageRequest.of(0, maxResults, new Sort(Sort.Direction.ASC, "popularity"));
		Page<Stock> page = this.stockRepository.findAll(pageable);

		List<StockVo> rets = new ArrayList<>();

		page.getContent().forEach(po -> {
			rets.add(BeanMapUtils.copy(po));
		});

		return rets;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: update</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param p
	 * 
	 * @see com.mtons.mblog.modules.service.StockService#update(com.mtons.mblog.
	 * modules.data.StockVo)
	 * 
	 */
	@Override
	public void update(StockVo p) {
		// TODO Auto-generated method stub

	}

	public List<StockVo> getStockRanking(String y,String m,String q,Integer max) {
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT temp.hl 'percentage',temp.stockcode,temp.stockname,temp.price from (")
				.append(" SELECT ROUND(((b.price - a.price) / a.price * 100),2) hl,a.stockcode,a.stockname,a.price from (")
				.append(" SELECT price,stockcode,stockname from mto_stock_history where createtime like '2019-02-01') a")
				.append(" LEFT JOIN (")
				.append(" SELECT price,stockcode,stockname from mto_stock_history where createtime like '2019-03-19') b")
				.append(" on a.stockcode = b.stockcode")
				.append(") temp where temp.hl is not null  ORDER BY hl,price LIMIT 100");
		List resultList = entityManager.createNativeQuery(sql.toString()).getResultList();
		return resultList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: findKeyWord</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param term
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.StockService#findKeyWord(java.lang.
	 * String)
	 * 
	 */
	@Override
	public List<Stock> findKeyWord(String term) {

		return this.stockRepository.findAll(stockWhere(term));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: saveUpdatedStock</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param t
	 * 
	 * @see
	 * com.mtons.mblog.quartz.service.StockService#saveUpdatedStock(com.mtons.
	 * mblog.quartz.entity.TUpdateStock)
	 * 
	 */
	@Override
	public void saveUpdatedStock(StockAttr t) {
		this.stockAttrRepository.save(t);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: listUpdatedStock</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param hashMap
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.quartz.service.StockService#listUpdatedStock(java.util.
	 * HashMap)
	 * 
	 */
	@Override
	public List<StockAttr> listStockAttrByUpdateTime(Date updateTime) {
		return this.stockAttrRepository.findAll(where(updateTime));
	}

	@SuppressWarnings("serial")
	private Specification<StockAttr> where(Date updateTime) {
		return new Specification<StockAttr>() {
			@Override
			public Predicate toPredicate(Root<StockAttr> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();
				String today = DateUtil.today() + " 23:59:59";
				predicates.add(criteriaBuilder.between(root.get("updatetime"), updateTime,
						DateUtil.parse(today, "yyyy-MM-dd hh:mm:ss")));
				return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
			}

		};
	}

	@SuppressWarnings("serial")
	private Specification<Stock> stockWhere(String kw) {
		return new Specification<Stock>() {
			@Override
			public Predicate toPredicate(Root<Stock> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();

				Predicate p = criteriaBuilder.like(root.get("stockname"), "%" + kw + "%");
				p = criteriaBuilder.or(p, criteriaBuilder.like(root.get("stockcode"), "%" + kw + "%"));
				predicates.add(p);

				return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
			}

		};
	}

	@SuppressWarnings("serial")
	private Specification<Stock> stockOrderWhere(String stockCode, String y, String q, String m, String order) {
		return new Specification<Stock>() {

			@Override
			public Predicate toPredicate(Root<Stock> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				String year = StrUtil.isBlank(y) ? DateUtil.thisYear() + "" : y;
				if (!StrUtil.isBlank(m)) {

				} else if (!StrUtil.isBlank(q)) {

				} else {

				}

				String quarter = StrUtil.isBlank(q) ? DateUtil.season(new Date()) + "" : q;
				String month = StrUtil.isBlank(m) ? DateUtil.thisMonth() + "" : m;
				return null;
			}

		};
	}

	@SuppressWarnings("serial")
	private Specification<StockHistory> stockHistoryWhere(String stockcode, String year, Integer quarter,
			Integer month) {
		return new Specification<StockHistory>() {
			@Override
			public Predicate toPredicate(Root<StockHistory> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();
				Predicate p = criteriaBuilder.equal(root.get("stockcode"), stockcode);
				String y = year;
				if (ObjectUtils.isEmpty(year)) {
					y = DateUtil.thisYear() + "";
				}
				if (quarter > 0 && quarter < 5) {
					p = criteriaBuilder.and(p, criteriaBuilder.equal(root.get("quarter"), quarter));
				}

				if (month != 0) {
					String m = month + "";
					if (month < 10) {
						m = "0" + m;
					}
					y = y + "-" + m;
				}
				p = criteriaBuilder.and(p, criteriaBuilder.like(root.get("createtime"), y + "%"));
				predicates.add(p);

				return query.where(predicates.toArray(new Predicate[predicates.size()]))
						.orderBy(criteriaBuilder.asc(root.get("createtime"))).getRestriction();
			}

		};
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: save</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param t
	 * 
	 * @see
	 * com.mtons.mblog.quartz.service.StockService#save(com.mtons.mblog.quartz.
	 * entity.TStock)
	 * 
	 */
	@Override
	public void save(Stock t) {
		this.stockRepository.save(t);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: saveHistoryPrice</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param sh
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.StockService#saveHistoryPrice(com.mtons.
	 * mblog.modules.entity.StockHistory)
	 * 
	 */
	@Override
	public int saveHistoryPrice(List<StockHistory> entitys) {
		String tplSql = "insert into mto_stock_history(stockid,stockcode,stockname,createtime,updatetime,price,quarter) values(?,?,?,?,?,?,?)";
		try {
			this.jdbcTemplate.batchUpdate(tplSql, setParameters(entitys));
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("保存出错了，直接跳过");
		}

		return 0;
	}

	private List<Object[]> setParameters(List<StockHistory> list) {
		List<Object[]> parameters = new ArrayList<Object[]>();
		for (StockHistory ik : list) {
			parameters.add(new Object[] { ik.getStockid(), ik.getStockcode(), ik.getStockname(), ik.getCreatetime(),
					ik.getUpdatetime(), ik.getPrice(), ik.getQuarter() });
		}
		return parameters;
	}

	@Override
	public List<StockHistory> findStockHistoryById(String stockcode, String year, Integer quarter, Integer month) {
		return stockHistroyRepository.findAll(stockHistoryWhere(stockcode, year, quarter, month));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: findStockHistroy</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.StockService#findStockHistroy()
	 * 
	 */
	@Override
	public List<StockHistory> findStockHistroy() {
		return this.stockHistroyRepository.findAll();
	}
}
